{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 《数据挖掘导论》第六章笔记"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一.问题定义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.关联分析简介：旨在探寻大型数据集中蕴含的有价值联系，这些联系可通过关联规则或频繁项集呈现。该技术广泛应用于生物信息学、医疗诊断、网页挖掘等多个领域。\n",
    "\n",
    "2.频繁项集相关概念\n",
    "项集：是由 0 个或多个项构成的集合，例如 {苹果，香蕉，橙子}。\n",
    "k - 项集：即包含 k 个项的集合。\n",
    "支持度计数（σ）：指包含特定项集的事务数量。比如，若有两个事务包含 {苹果，香蕉，橙子}，则 σ(苹果，香蕉，橙子)=2。\n",
    "支持度（s）：是包含项集的事务数与总事务数的比例，如 s (苹果，香蕉，橙子)=2 / 总事务数。\n",
    "频繁项集：满足最小支持度阈值（minsup）要求的所有项集。\n",
    "\n",
    "3.关联规则详述\n",
    "定义：呈现为 X→Y 的形式，其中 X 和 Y 是不相交的项集，例如 {面包，果酱}→{黄油}。\n",
    "支持度：用于衡量项集出现的频繁程度，计算公式为 s (X→Y)=σ(X∪Y)/N，N 为事务总数。\n",
    "置信度：用于确定在包含 X 的事务中，Y 出现的频繁程度，公式为 c (X→Y)=σ(X∪Y)/σ(X)。\n",
    "\n",
    "4.关联规则发现目标：要找出所有支持度大于等于 minsup，且置信度大于等于 minconf 的规则。传统的 Brute - force approach 方法，需计算每个可能规则的支持度和置信度，计算成本极高。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二.频繁项集的产生"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.暴力法（Brute - force 方法）\n",
    "操作步骤：将格结构中的每个项集都当作候选项集，逐一与每个事务进行对比，以此确定每个候选项集的支持度计数。\n",
    "时间复杂度：约为 O (NMw)，计算开销极大。\n",
    "\n",
    "2.先验原理（Apriori 原理）\n",
    "核心内容：若一个项集是频繁的，那么它的所有子集必然也是频繁的；反之，若一个项集是非频繁的，其所有超集也必定是非频繁的。这一基于支持度进行筛选的策略被称为基于支持度的剪枝。\n",
    "\n",
    "3.Apriori 算法生成频繁项集\n",
    "候选的产生与剪枝\n",
    "候选项集的产生：从频繁（k - 1）- 项集生成新的候选 k - 项集。\n",
    "候选项集的剪枝：运用基于支持度的剪枝策略，去除部分候选 k - 项集。\n",
    "支持度计数：确定在 apriori - gen 函数的候选项剪枝步骤中留存的每个候选项集的出现频繁程度。\n",
    "计算复杂度影响因素\n",
    "支持度阈值：降低支持度阈值，会使更多项集被认定为频繁，进而增加计算复杂度。\n",
    "项数：项数增多时，存储项的支持度计数所需的空间也会增加。\n",
    "事务数：由于 Apriori 算法需反复扫描数据集，所以其运行时间会随事务数的增加而延长。\n",
    "事务的平均宽度：事务平均宽度增加，频繁项集的最大长度也会随之增加，这会导致支持度计数时 Hash 树的遍历次数增多。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三.规则的产生"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1.关联规则提取\n",
    "忽略规则类型：摒弃那些前件或后件为空的规则。\n",
    "规则生成方式：每个频繁 k - 项集最多可生成 2^k - 2 个关联规则。通过将项集 Y 分割为两个非空子集 X 和 Y - X，确保 X→Y - X 满足置信度阈值。\n",
    "\n",
    "2.计算置信度：通常无需再次扫描事务数据集，而是借助频繁项集的支持度计数来计算置信度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "关联分析作为一种数据挖掘技术，专注于发现大型数据集中的有意义联系。其关键在于频繁项集的生成以及关联规则的提取。借助 Apriori 算法及其先验原理，还有基于支持度的剪枝策略，能够有效降低计算复杂度，提升挖掘效率。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 五.作业"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第二题：计算项集支持度\n",
    "数据表如下所示：\n",
    "顾客ID\t事务ID\t购买项\n",
    "1\t0001\t{a,d,e}\n",
    "2\t0024\t{a,b,c,e}\n",
    "3\t0012\t{a,b,c,e}\n",
    "4\t0031\t{a,d,e}\n",
    "5\t0015\t{b,c,e}\n",
    "6\t0022\t{b,d,e}\n",
    "7\t0029\t{c,d}\n",
    "8\t0040\t{a,b,c}\n",
    "9\t0033\t{a,b,e}\n",
    "10\t0038\t{a,b,e}\n",
    "\n",
    "a. 计算项集{e}的支持度\n",
    "b. 计算项集*{b,d}*的支持度\n",
    "c. 计算项集{b,d,e}的支持度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "项集{e}的支持度: 0.8\n",
      "项集{b,d}的支持度: 0.1\n",
      "项集{b,d,e}的支持度: 0.1\n"
     ]
    }
   ],
   "source": [
    "data = [\n",
    "    {'顾客ID': 1, '事务ID': '0001', '购买项': {'a', 'd', 'e'}},\n",
    "    {'顾客ID': 2, '事务ID': '0024', '购买项': {'a', 'b', 'c', 'e'}},\n",
    "    {'顾客ID': 3, '事务ID': '0012', '购买项': {'a', 'b', 'c', 'e'}},\n",
    "    {'顾客ID': 4, '事务ID': '0031', '购买项': {'a', 'd', 'e'}},\n",
    "    {'顾客ID': 5, '事务ID': '0015', '购买项': {'b', 'c', 'e'}},\n",
    "    {'顾客ID': 6, '事务ID': '0022', '购买项': {'b', 'd', 'e'}},\n",
    "    {'顾客ID': 7, '事务ID': '0029', '购买项': {'c', 'd'}},\n",
    "    {'顾客ID': 8, '事务ID': '0040', '购买项': {'a', 'b', 'c'}},\n",
    "    {'顾客ID': 9, '事务ID': '0033', '购买项': {'a', 'b', 'e'}},\n",
    "    {'顾客ID': 10, '事务ID': '0038', '购买项': {'a', 'b', 'e'}}\n",
    "]\n",
    "\n",
    "# 计算项集{e}的支持度\n",
    "count_e = sum(1 for row in data if 'e' in row['购买项'])\n",
    "support_e = count_e / len(data)\n",
    "print(\"项集{e}的支持度:\", support_e)\n",
    "\n",
    "# 计算项集{b,d}的支持度\n",
    "count_bd = sum(1 for row in data if 'b' in row['购买项'] and 'd' in row['购买项'])\n",
    "support_bd = count_bd / len(data)\n",
    "print(\"项集{b,d}的支持度:\", support_bd)\n",
    "\n",
    "# 计算项集{b,d,e}的支持度\n",
    "count_bde = sum(1 for row in data if 'b' in row['购买项'] and 'd' in row['购买项'] and 'e' in row['购买项'])\n",
    "support_bde = count_bde / len(data)\n",
    "print(\"项集{b,d,e}的支持度:\", support_bde)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第四题：判断度量的性质\n",
    "(a) 特征规则的最小置信度 ζ\n",
    "(b) 区分规则的最小置信度 η\n",
    "(c) 将最小值函数改为最大值函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征规则的最小置信度 ζ: 0.7\n",
      "区分规则的最小置信度 η: 0.6\n",
      "最大值: 5\n"
     ]
    }
   ],
   "source": [
    "# 假设已经有了计算特征规则置信度的函数\n",
    "def calculate_characteristic_confidence():\n",
    "    # 这里只是一个占位，实际需要根据具体规则计算\n",
    "    return 0.7\n",
    "\n",
    "# 假设已经有了计算区分规则置信度的函数\n",
    "def calculate_discriminant_confidence():\n",
    "    # 这里只是一个占位，实际需要根据具体规则计算\n",
    "    return 0.6\n",
    "\n",
    "# (a) 获取特征规则的最小置信度 ζ\n",
    "zeta = calculate_characteristic_confidence()\n",
    "print(\"特征规则的最小置信度 ζ:\", zeta)\n",
    "\n",
    "# (b) 获取区分规则的最小置信度 η\n",
    "eta = calculate_discriminant_confidence()\n",
    "print(\"区分规则的最小置信度 η:\", eta)\n",
    "\n",
    "# (c) 将最小值函数改为最大值函数\n",
    "values = [3, 1, 5, 2]\n",
    "max_value = max(values)\n",
    "print(\"最大值:\", max_value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第六题：计算项集支持度\n",
    "数据表如下所示：\n",
    "事务ID\t购买项\n",
    "1\t{牛奶, 啤酒, 尿布}\n",
    "2\t{面包, 黄油, 牛奶}\n",
    "3\t{牛奶, 尿布, 饼干}\n",
    "4\t{面包, 黄油, 饼干}\n",
    "5\t{啤酒, 饼干, 尿布}\n",
    "6\t{牛奶, 尿布, 面包, 黄油}\n",
    "7\t{面包, 黄油, 尿布}\n",
    "8\t{啤酒, 尿布}\n",
    "9\t{牛奶, 尿布, 面包, 黄油}\n",
    "10\t{啤酒, 饼干}\n",
    "a. 计算项集{e}的支持度\n",
    "b. 计算项集{b,d}的支持度\n",
    "c. 计算项集{b, d, e}的支持度\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "项集{e}的支持度: 0.0\n",
      "项集{b,d}的支持度: 0.3\n",
      "项集{b,d,e}的支持度: 0.3\n"
     ]
    }
   ],
   "source": [
    "data = [\n",
    "    {'事务ID': 1, '购买项': {'牛奶', '啤酒', '尿布'}},\n",
    "    {'事务ID': 2, '购买项': {'面包', '黄油', '牛奶'}},\n",
    "    {'事务ID': 3, '购买项': {'牛奶', '尿布', '饼干'}},\n",
    "    {'事务ID': 4, '购买项': {'面包', '黄油', '饼干'}},\n",
    "    {'事务ID': 5, '购买项': {'啤酒', '饼干', '尿布'}},\n",
    "    {'事务ID': 6, '购买项': {'牛奶', '尿布', '面包', '黄油'}},\n",
    "    {'事务ID': 7, '购买项': {'面包', '黄油', '尿布'}},\n",
    "    {'事务ID': 8, '购买项': {'啤酒', '尿布'}},\n",
    "    {'事务ID': 9, '购买项': {'牛奶', '尿布', '面包', '黄油'}},\n",
    "    {'事务ID': 10, '购买项': {'啤酒', '饼干'}}\n",
    "]\n",
    "\n",
    "# 计算项集{e}的支持度\n",
    "count_e = sum(1 for row in data if 'e' in row['购买项'])\n",
    "support_e = count_e / len(data)\n",
    "print(\"项集{e}的支持度:\", support_e)\n",
    "\n",
    "# 计算项集{b,d}的支持度（这里假设b是面包，d是尿布）\n",
    "count_bd = sum(1 for row in data if '面包' in row['购买项'] and '尿布' in row['购买项'])\n",
    "support_bd = count_bd / len(data)\n",
    "print(\"项集{b,d}的支持度:\", support_bd)\n",
    "\n",
    "# 计算项集{b,d,e}的支持度（这里假设b是面包，d是尿布，e是黄油）\n",
    "count_bde = sum(1 for row in data if '面包' in row['购买项'] and '尿布' in row['购买项'] and '黄油' in row['购买项'])\n",
    "support_bde = count_bde / len(data)\n",
    "print(\"项集{b,d,e}的支持度:\", support_bde)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第八题：判断度量的性质\n",
    "(a) 特征规则的最小置信度 ζ\n",
    "(b) 区分规则的最小置信度 η\n",
    "(c) 将最小值函数改为最大值函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征规则的最小置信度 ζ: 0.7\n",
      "区分规则的最小置信度 η: 0.6\n",
      "最大值: 5\n"
     ]
    }
   ],
   "source": [
    "# 假设这里有计算特征规则置信度的函数，你需要根据实际规则来实现\n",
    "def calculate_characteristic_confidence():\n",
    "    return 0.7  # 这里只是一个示例值，实际需根据具体规则计算\n",
    "\n",
    "# 假设这里有计算区分规则置信度的函数，你需要根据实际规则来实现\n",
    "def calculate_discriminant_confidence():\n",
    "    return 0.6  # 这里只是一个示例值，实际需根据具体规则计算\n",
    "\n",
    "# (a) 获取特征规则的最小置信度 ζ\n",
    "zeta = calculate_characteristic_confidence()\n",
    "print(\"特征规则的最小置信度 ζ:\", zeta)\n",
    "\n",
    "# (b) 获取区分规则的最小置信度 η\n",
    "eta = calculate_discriminant_confidence()\n",
    "print(\"区分规则的最小置信度 η:\", eta)\n",
    "\n",
    "# (c) 将最小值函数改为最大值函数\n",
    "values = [3, 1, 5, 2]\n",
    "max_value = max(values)\n",
    "print(\"最大值:\", max_value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第十题\n",
    "(a) 构造以上候选3-项集的Hash树。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "class HashTreeNode:\n",
    "    def __init__(self):\n",
    "        self.children = {}\n",
    "        self.is_leaf = False\n",
    "        self.itemsets = []\n",
    "\n",
    "def insert_into_hash_tree(node, itemset):\n",
    "    if len(itemset) == 0:\n",
    "        node.is_leaf = True\n",
    "        node.itemsets.append(itemset)\n",
    "        return\n",
    "    first_item = itemset[0]\n",
    "    if first_item not in node.children:\n",
    "        node.children[first_item] = HashTreeNode()\n",
    "    insert_into_hash_tree(node.children[first_item], itemset[1:])\n",
    "\n",
    "def construct_hash_tree(candidate_itemsets):\n",
    "    root = HashTreeNode()\n",
    "    for itemset in candidate_itemsets:\n",
    "        insert_into_hash_tree(root, itemset)\n",
    "    return root\n",
    "\n",
    "# 示例候选3-项集\n",
    "candidate_3_itemsets = [['a', 'b', 'c'], ['a', 'b', 'd'], ['a', 'c', 'e'], ['b', 'c', 'd']]\n",
    "hash_tree = construct_hash_tree(candidate_3_itemsets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第十二题\n",
    "(b) 利用(a)的相依表，按照下面的度量计算并依递减序确定规则的秩。\n",
    "假设我们已经计算出了相依表，现在使用以下度量进行计算：\n",
    "\n",
    "支持度：P(X,Y)\n",
    "置信度：P(Y|X)\n",
    "兴趣因子：Interst(X→Y)=P(X,Y)P(X)P(Y)\n",
    "IS值：IS(X→Y)=P(X,Y)P(X)P(Y)√\n",
    "Klossen：Klossen(X→Y)=P(X,Y)−−−−−−−√×(P(Y|X)−P(Y))\n",
    "，其中P(Y|X)=P(X,Y)P(X)\n",
    "。\n",
    "几率：(X→Y)=P(X,Y)P(X¯,Y¯)P(X,Y¯)P(X¯,Y)\n",
    "。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "支持度: 0.3\n",
      "置信度: 0.6\n",
      "兴趣因子: 0.24\n",
      "IS值: 0.6708203932499369\n",
      "Klossen: 0.10954451150103318\n",
      "几率: 7.499999999999996\n"
     ]
    }
   ],
   "source": [
    "# 假设这些函数已经根据实际数据计算出了相应的概率值\n",
    "def P_X_Y():\n",
    "    return 0.3  # 示例值，实际需根据数据计算\n",
    "\n",
    "def P_X():\n",
    "    return 0.5  # 示例值，实际需根据数据计算\n",
    "\n",
    "def P_Y():\n",
    "    return 0.4  # 示例值，实际需根据数据计算\n",
    "\n",
    "# 计算支持度\n",
    "support = P_X_Y()\n",
    "print(\"支持度:\", support)\n",
    "\n",
    "# 计算置信度\n",
    "confidence = P_X_Y() / P_X()\n",
    "print(\"置信度:\", confidence)\n",
    "\n",
    "# 计算兴趣因子\n",
    "interest = P_X_Y() / P_X() * P_Y()\n",
    "print(\"兴趣因子:\", interest)\n",
    "\n",
    "# 计算IS值\n",
    "is_value = P_X_Y() / ((P_X() * P_Y()) ** 0.5)\n",
    "print(\"IS值:\", is_value)\n",
    "\n",
    "# 计算Klossen\n",
    "p_y_given_x = P_X_Y() / P_X()\n",
    "klossen = (P_X_Y() ** 0.5) * (p_y_given_x - P_Y())\n",
    "print(\"Klossen:\", klossen)\n",
    "\n",
    "# 计算几率\n",
    "p_not_x_y_not = 1 - P_X_Y() - P_X() + P_X_Y()\n",
    "p_x_not_y = P_X() - P_X_Y()\n",
    "p_not_x_y = P_Y() - P_X_Y()\n",
    "odds = P_X_Y() * p_not_x_y_not / (p_x_not_y * p_not_x_y)\n",
    "print(\"几率:\", odds)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第十八题：计算ϕ\n",
    "系数\n",
    "表6-26 显示了二元变量 A\n",
    " 和 B\n",
    " 在控制变量 C\n",
    " 的不同值上的 2×2×2\n",
    " 的相依表。我们需要计算 ϕ\n",
    " 系数，公式为：\n",
    "ϕ(A,B)=P(A,B)−P(A)P(B)P(A)P(B)(1−P(A))(1−P(B))−−−−−−−−−−−−−−−−−−−−−−−−−−√"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "φ系数: 0.40824829046386296\n"
     ]
    }
   ],
   "source": [
    "# 假设这些函数已经根据实际数据计算出了相应的概率值\n",
    "def P_A_B():\n",
    "    return 0.3  # 示例值，实际需根据数据计算\n",
    "\n",
    "def P_A():\n",
    "    return 0.5  # 示例值，实际需根据数据计算\n",
    "\n",
    "def P_B():\n",
    "    return 0.4  # 示例值，实际需根据数据计算\n",
    "\n",
    "# 计算φ系数\n",
    "numerator = P_A_B() - P_A() * P_B()\n",
    "denominator = ((P_A() * P_B() * (1 - P_A()) * (1 - P_B())) ** 0.5)\n",
    "phi_coefficient = numerator / denominator\n",
    "print(\"φ系数:\", phi_coefficient)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "第二十题\n",
    "表6-19 高清晰度电视和健身器销售之间的2路相依表\n",
    "买HDTV\t买健身    总数\n",
    "是\t    否\t      99\n",
    "否\t    是\t      54\n",
    "是\t    否\t      81\n",
    "否\t    否\t      66\n",
    "总数\t180\t      120\n",
    "表6-20 3路相依表的例子\n",
    "顾客组\t买HDTV\t买健身器\t总数\n",
    "大学生 \t  是\t   否\t    10\n",
    "         是\t       9\t\n",
    "         否\t      30\t\n",
    "        总数\t  10\t    34\n",
    "在职人员  是\t  否\t     72\n",
    "         是       50\t\n",
    "         否\t      36\t\n",
    "        总数\t 170\t    86 \n",
    "        \n",
    "(a) 计算两个表的几率\n",
    "(b) 计算两个表的 ϕ系数\n",
    "(c) 计算两个表的兴趣因子"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**第二十题**\n",
    "表6-19 高清晰度电视和健身器销售之间的2路相依表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 买HDTV | 买健身器 | 总数 |\n",
    "| ---- | ---- | ---- |\n",
    "| 是 | 否 | 99 |\n",
    "| 否 | 是 | 54 |\n",
    "| 是 | 否 | 81 |\n",
    "| 否 | 否 | 66 |\n",
    "| 总数 | 180 | 120 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "表6-20 3路相依表的例子"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 顾客组 | 买HDTV | 买健身器 | 总数 |\n",
    "| ---- | ---- | ---- | ---- |\n",
    "| 大学生 | 是 | 否 | 10 |\n",
    "|  | 是 | 9 |  |\n",
    "|  | 否 | 30 |  |\n",
    "|  | 总数 | 10 | 34 |\n",
    "| 在职人员 | 是 | 否 | 72 |\n",
    "|  | 是 | 50 |  |\n",
    "|  | 否 | 36 |  |\n",
    "|  | 总数 | 170 | 86 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(a) 计算两个表的几率"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "购买HDTV的概率P(HDTV)为：0.6\n",
      "购买健身器的概率P(健身器)为：0.4\n"
     ]
    }
   ],
   "source": [
    "# 表6-19的数据\n",
    "table19_data = [\n",
    "    ['是', '否', 99],\n",
    "    ['否', '是', 54],\n",
    "    ['是', '否', 81],\n",
    "    ['否', '否', 66],\n",
    "    ['总数', 180, 120]\n",
    "]\n",
    "\n",
    "# 计算总人数\n",
    "total_people_19 = sum(table19_data[-1][1:])\n",
    "\n",
    "# 计算购买HDTV的人数\n",
    "buy_hdtv_people_19 = table19_data[0][2] + table19_data[2][2]\n",
    "\n",
    "# 计算购买健身器的人数\n",
    "buy_fitness_people_19 = table19_data[1][2] + table19_data[3][2]\n",
    "\n",
    "# 计算购买HDTV的概率\n",
    "p_hdtv_19 = buy_hdtv_people_19 / total_people_19\n",
    "print(f\"购买HDTV的概率P(HDTV)为：{p_hdtv_19}\")\n",
    "\n",
    "# 计算购买健身器的概率\n",
    "p_fitness_19 = buy_fitness_people_19 / total_people_19\n",
    "print(f\"购买健身器的概率P(健身器)为：{p_fitness_19}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "大学生购买HDTV的概率P(大学生, HDTV)为：0.0\n"
     ]
    }
   ],
   "source": [
    "# 表6-20的数据（这里仅以大学生为例，你可以根据实际情况扩展到在职人员等其他分组）\n",
    "table20_student_data = [\n",
    "    ['大学生', '是', '否', 10],\n",
    "    ['', '是', '9', ''],\n",
    "    ['', '否', '30', ''],\n",
    "    ['', '总数', '10', '34']\n",
    "]\n",
    "\n",
    "# 计算大学生总数\n",
    "total_student_20 = int(table20_student_data[-1][-1])\n",
    "\n",
    "# 计算大学生购买HDTV的人数\n",
    "student_buy_hdtv_20 = 0\n",
    "for row in table20_student_data:\n",
    "    if row[0] == '大学生' and row[1] == '是':\n",
    "        try:\n",
    "            student_buy_hdtv_20 = int(row[2])\n",
    "            break\n",
    "        except ValueError:\n",
    "            pass\n",
    "\n",
    "# 计算大学生购买HDTV的概率\n",
    "p_student_hdtv_20 = student_buy_hdtv_20 / total_student_20\n",
    "print(f\"大学生购买HDTV的概率P(大学生, HDTV)为：{p_student_hdtv_20}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(b) 计算两个表的 ϕ系数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "表6-19的φ系数为: 0.09799919151000505\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "# 表6-19的数据\n",
    "a = 99\n",
    "b = 54\n",
    "c = 81\n",
    "d = 66\n",
    "\n",
    "numerator = a * d - b * c\n",
    "denominator = math.sqrt((a + b) * (c + d) * (a + c) * (b + d))\n",
    "\n",
    "phi_coefficient = numerator / denominator\n",
    "print(\"表6-19的φ系数为:\", phi_coefficient)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "表6-20（大学生组）的φ系数为: -0.5960395606792698\n"
     ]
    }
   ],
   "source": [
    "import math\n",
    "\n",
    "# 买HDTV且不买健身器的人数\n",
    "a = 10\n",
    "# 买HDTV且买健身器的人数\n",
    "b = 9\n",
    "# 不买HDTV但买健身器的人数\n",
    "c = 30\n",
    "# 重新计算总数\n",
    "total = (a + b) + c\n",
    "# 不买HDTV也不买健身器的人数\n",
    "d = total - (a + b + c)\n",
    "\n",
    "numerator = a * d - b * c\n",
    "denominator = math.sqrt((a + b) * (c + d) * (a + c) * (b + d))\n",
    "\n",
    "phi_coefficient = numerator / denominator\n",
    "print(\"表6-20（大学生组）的φ系数为:\", phi_coefficient)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(c) 计算两个表的兴趣因子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "表6-19的兴趣因子为: 2.125\n"
     ]
    }
   ],
   "source": [
    "# 表6-19的数据\n",
    "table19_data = [\n",
    "    ['是', '否', 99],\n",
    "    ['否', '是', 54],\n",
    "    ['是', '否', 81],\n",
    "    ['否', '否', 66],\n",
    "    ['总数', 180, 120]\n",
    "]\n",
    "\n",
    "# 计算总人数\n",
    "total_people_19 = sum(table19_data[-1][1:])\n",
    "\n",
    "# 计算购买HDTV的人数\n",
    "buy_hdtv_people_19 = table19_data[0][2] + table19_data[2][2]\n",
    "\n",
    "# 计算购买健身器的人数\n",
    "buy_fitness_people_19 = table19_data[1][2] + table19_data[3][2]\n",
    "\n",
    "# 计算购买HDTV的概率\n",
    "p_hdtv_19 = buy_hdtv_people_19 / total_people_19\n",
    "\n",
    "# 计算购买健身器的概率\n",
    "p_fitness_19 = buy_fitness_people_19 / total_people_19\n",
    "\n",
    "# 计算实际购买组合的顾客数\n",
    "actual_combination_customers_19 = table19_data[0][2] + table19_data[1][2]\n",
    "\n",
    "# 计算预期购买组合的顾客数\n",
    "expected_combination_customers_19 = p_hdtv_19 * p_fitness_19 * total_people_19\n",
    "\n",
    "# 计算兴趣因子\n",
    "lift_19 = actual_combination_customers_19 / expected_combination_customers_19\n",
    "print(f\"表6-19的兴趣因子为: {lift_19}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
